#ifndef __PARK_H__
#define __PARK_H__

#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>

#include "os_sys.h"
#include "param.h"
#include "radar.h"
#include "drv_misc.h"

#define RADAR_DATA_BUFF 96
#define RADAR_HISTORY_BUFF_SIZE 96
#define MEDIAN_FILTER_WINSIZE 5
#define RADAR_BURST_DETECT_CNT 10
#define RADAR_AMP_THRESHOLD 60
#define RADAR_AMP_UP_THRESHOLD 60000
#define RADAR_UNSTABLE_COUNT 300
#define RADAR_MAX_DIST_THRESHOLD 500
#define RADAR_AMP_COVER 800
#define RADAR_DATA_SAVE_LOG_CNT 32
#define MAX_CMD_BUFF_CNT 12
#define CONFLICT_FUSING_CNT 4
#define FUSING_TIMEOUT 10 * 60
#define PARKINGOUT_TIMEOUT_IN_S 120
#define MIDDLE_LOW_D_THRESHOLD (8.f)
#define MIDDLE_MIDDLE_D_THRESHOLD (15.f)
#define MIDDLE_HIGH_D_THRESHOLD (56.f)
#define RADAR_MAX_ZERO_FREE_COUNT (30)
#define RADAR_MAX_STD_CALC_COUNT (32)

#define RADAR_STD_RATIO (3.f)
#define RADAR_MAX_TRIGGER_COUNT (5)
#define RADAR_MIN_STD_THRESHOLD (15.f)
#define RADAR_MAX_ZERO_TRIGGER_COUNT (1)
#define RADAR_MAX_PROTECT_COUNT (3)

#define UNSTABLE_EXIT_COUNT (8)

typedef struct ParkCtx_ ParkCtx_t;

typedef struct PollingTimer_ {
  bool enable;
  uint64_t interval;
  uint64_t last_timeout;
  bool ever_time_out;
} PollingTimer_t;

typedef enum {
  PIPE_STATE_DETECT,  /*SOC power off, detect state*/
  PIPE_STATE_TRIG,    /*SOC power on, but no alg result return*/
  PIPE_STATE_ALG,     /*SOC power on, alg result return*/
  PIPE_STATE_UPDATE,  /*SOC power on/off, update state*/
  PIPE_STATE_FACTORY, /*SOC power on, facstory state,into produce flow*/
  PIPE_STATE_LOWBATT  /*battery low protect mode*/
} SocState_e;

typedef enum {
  TRIG_STATUS_OFF = 0,
  TRIG_STATUS_ON,
  TRIG_STATUS_BUF,
} TrigStatus_e;

typedef enum {
  CMD_ID_ALG_RESULT = 0,
  CMD_ID_SOC_PWDN,
  CMD_ID_KICK_WDT,
  CMD_ID_UPDATE,
  CMD_ID_FACTORY,
  CMD_ID_DEBUG_MODE
} CmdId_e;

typedef enum {
  STATUS_INVALID = 0,
  STATUS_NO_OBJ,
  STATUS_OBJ_ENTER,
  STATUS_OBJ_EXIST,
  STATUS_OBJ_LEAVE,
} ObjStatus_t;

typedef enum {
  ERROR_NO = 0,
  ERROR_COVER,
  ERROR_DIRECT,
  ERROR_WEEK
} RadarError_e;

typedef enum {
  TRIG_TYPE_NO = 0,            /*not any event*/
  TRIG_TYPE_PARK = 1,          /*parking event */
  TRIG_TYPE_PWRON = 2,         /*fisrt power on event*/
  TRIG_TYPE_LOW_BATT = 4,      /*battery low capacity event*/
  TRIG_TYPE_HEART = 8,         /*timeout heart trigger event*/
  TRIG_TYPE_BATT_DOOR = 16,    /*battery door open event*/
  TRIG_TYPE_RESOTRE = 32,      /*restore all parameters event*/
  TRIG_TYPE_DEBUG = 64,        /*debug mode event*/
  TRIG_TYPE_RADAR_FAULT = 128, /*radar fault event*/
  TRIG_TYPE_RADAR_COVER = 256, /*radar is covered event*/
  TRIG_TYPE_SNAPSHOT = 512,    /*timing snapshot event*/
  TRIG_TYPE_UPDATE = 1024,     /*update*/
  TRIG_TYPE_PLATE = 2048       /*车牌确认触发事件*/
} TrigType_e;

typedef enum {
  PARK_TYPE_IN = 1,         /*car entering*/
  PARK_TYPE_STABLE = 2,     /*car absent*/
  PARK_TYPE_OUT = 4,        /*car leaving*/
  PARK_TYPE_FREE = 8,       /*parking lot empty*/
  PARK_TYPE_RADAR_MAX = 16, /*radar reaches max value*/
} ParkType_e;

typedef enum park_msgid_ {
  PARK_MSGID_SOC_PWRDOWN = 0, /*关闭SOC电源*/
  PARK_MSGID_ALG_RESULT,      /*配置算法结果*/
  PARK_MSGID_UPDATE,          /*配置升级状态*/
  PARK_MSGID_WDT,             /*喂狗*/
  PARK_DEBUG_MODE             /*进入调试和自恢复模式*/
} ParkMsgId_e;

typedef struct TriggerInfo_ {
  uint32_t trig_type;
  uint8_t park_state;
  uint16_t empty_threshold;
  uint16_t is_car_change;
  uint16_t radar_data;
} TriggerInfo_t;

typedef struct alg_result {
  uint8_t reco;
  uint8_t has_plate;
} AlgResult_t;

typedef enum {
  SOC_STATUS_POWERON = 0,
  SOC_STATUS_POWEROFF,
  SOC_STATUS_UPGRADE,
} SocWorkStatus_e;

typedef struct DataBuff_ {
  RadarData_t data[RADAR_DATA_BUFF];
  int front; // 队头位置
  int count;
} DataBuff_t;

typedef struct radar_history_ {
  RadarData_t data[RADAR_HISTORY_BUFF_SIZE];
  int count;
} radar_history_t;

typedef struct tirggerHistory_{
  int triggerCount;        // 重复触发次数
  int lastTriggerDist;     // 上一次触发距离
  float lastTriggerMean;     // 上一次触发均值
  float lastTriggerStd;     // 上一次触发方差
  bool bObjStableMode;     // 长时间遮挡模式
}tirggerHistory;

typedef struct RadarProc_ {
  DataBuff_t buff;               // 雷达数据
  bool isCarChanged;             // 是否换车标志位
  bool isLastCarChanged;         // 唤醒前是否换车标志位
  int stableZeroCount;           // 稳定的非法值计数(&空闲时的非法值计数)
  int stableZeroTriggerCount;    // 停稳后0数据触发次数
  // int inStableCount;          // 入场后停稳状态计数
  int outStableCount;            // 出场后空闲状态计数
  int stableUnstableCount;       // 突破停稳状态计数
  int freeUnstableCount;         // 突破空闲状态计数
  uint32_t event_count;          // 换车标志位计算相关
  int32_t lastParkStatus;        // 上次触发时的泊位状态
  int parkStableCount;           // 维持当前泊位状态计数
  int newestClock;               // 最近一次雷达处理时钟
  int lastEventClock;            // 最近一次雷达触发时钟
  int radarFreeDist;             // 雷达空闲时的最大距离
  int outProbe;                  // 出场可能性
  tirggerHistory triggerHistory; // 触发历史记录
} RadarProc_t;

typedef struct MsgCmd_ {
  uint32_t id;
  uint32_t len;
  uint8_t data[8];
} MsgCmd_t;

typedef struct DebugMode_ {
  uint32_t enable;
  uint32_t time;
} __attribute__((aligned(4))) DebugMode_t;

typedef struct ParkCtx_ {
  bool first_poweron;
  bool park_stable;
  SocState_e state;
  ParkType_e park_state; /*bit 0~3:alg state ; bit 4~7:radar state*/
  RadarProc_t radar_proc;
  uint32_t trig_count;
  PollingTimer_t heart_timer;
  PollingTimer_t battdoor_timer;
  PollingTimer_t battlow_timer;
  PollingTimer_t radar_fault_timer;
  PollingTimer_t parkstable_zero_radar_timer; // 雷达非法数据唤醒策略
  PollingTimer_t parkin_timer;
  PollingTimer_t parkout_timer;
  PollingTimer_t snapshot_timer;
  PollingTimer_t wdt_timer;
  PollingTimer_t plate_timer;                 //停车确认事件计时器
  SocState_e last_state;
  uint32_t state_count;
  int32_t debug_pending;
  uint32_t soc_on_timeout;
  uint32_t cur_trig_type;
  bool first_snapshot;
  RadarData_t last_radar;
  bool has_plate;
  uint32_t plate_event;                     //车牌事件，只有值为1的时候才会使能
} ParkCtx_t;

typedef struct BusWorkInfo_ {
  ParamInfo_t param;
  ParamAdvInfo_t param_adv;
  DevTime_t cur_time;
  uint64_t time_stamp;
  bool radar_shut;
} BusWorkInfo_t;

typedef int (*SocPowerCb)(ParkCtx_t *ctx, ParamInfo_t *p,
                          SocWorkStatus_e soc_sta);

int Park_Init(ParkCtx_t *ctx, ParamInfo_t *p);
int Park_SetMiscCallback(SocPowerCb pwr_cb);
int Park_Unint(ParkCtx_t *ctx);
bool Park_Exec(ParkCtx_t *ctx, BusWorkInfo_t* bus_info);
int Park_GetTriggerType(TriggerInfo_t *info);
int Park_SetAlgResult(AlgResult_t *result);
int Park_SetSocPowerDown();
int Park_SetUpdate(uint8_t update);
int Park_SetFactoryMode(uint8_t factory);
int Park_WdtKick();
int Park_GetAllData(ParkCtx_t *ctx, char *data, int limit_cnt);
int Park_SetDebugMode(DebugMode_t *set_mode);

int Park_GetLastRadar(ParkCtx_t * ctx, RadarData_t* data);
int Park_SaveCtx(ParkCtx_t * ctx);
int Park_RestoreCtx(ParkCtx_t * ctx);
int Park_SaveRebootFlag(uint32_t mode);
bool Park_IsRebootFlag(uint32_t *mode);
int Park_ClearRebootFlag(void);

#ifdef __cplusplus
}
#endif

#endif
